import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pandas import plotting
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.neighbors import KNeighborsClassifier
from sklearn import svm
from sklearn import metrics
from sklearn.tree import DecisionTreeClassifier

# 设置颜色主题
antV = ['#1890FF', '#2FC25B', '#FACC14', '#223273', '#8543E0', '#13C2C2', '#3436c7', '#F04864']

# 导入数据集
iris = pd.read_csv(r'D:\iris.csv', usecols=[0, 1, 2, 3, 4])

# 输出基本信息
print(iris.info())
print(iris.head())
print(iris.describe())

# 设置seaborn样式
sns.set_style("whitegrid")
plt.style.use('seaborn')

# 绘制小提琴图
def plot_violin():
    f, axes = plt.subplots(2, 2, figsize=(8, 8), sharex=True)
    sns.despine(left=True)
    sns.violinplot(x='Species', y='SepalLengthCm', data=iris, palette=antV, ax=axes[(0, 0)])
    sns.violinplot(x='Species', y='SepalWidthCm', data=iris, palette=antV, ax=axes[(0, 1)])
    sns.violinplot(x='Species', y='PetalLengthCm', data=iris, palette=antV, ax=axes[(1, 0)])
    sns.violinplot(x='Species', y='PetalWidthCm', data=iris, palette=antV, ax=axes[(1, 1)])
    plt.show()

plot_violin()

# 绘制点图
def plot_point():
    f, axes = plt.subplots(2, 2, figsize=(8, 8), sharex=True)
    sns.despine(left=True)
    sns.pointplot(x='Species', y='SepalLengthCm', data=iris, color=antV[0], ax=axes[0, 0])
    sns.pointplot(x='Species', y='SepalWidthCm', data=iris, color=antV[0], ax=axes[0, 1])
    sns.pointplot(x='Species', y='PetalLengthCm', data=iris, color=antV[0], ax=axes[1, 0])
    sns.pointplot(x='Species', y='PetalWidthCm', data=iris, color=antV[0], ax=axes[1, 1])
    plt.show()

plot_point()

# 绘制散点图矩阵
def plot_pairplot():
    g = sns.pairplot(data=iris, palette=antV, hue='Species')
    plt.show()

plot_pairplot()

# 使用 Andrews Curves
def plot_andrews_curves():
    plt.subplots(figsize=(10, 8))
    plotting.andrews_curves(iris, 'Species', colormap='cool')
    plt.show()

plot_andrews_curves()

# 绘制线性回归图
def plot_lm():
    g = sns.lmplot(data=iris, x='SepalWidthCm', y='SepalLengthCm', palette=antV, hue='Species')
    g = sns.lmplot(data=iris, x='PetalWidthCm', y='PetalLengthCm', palette=antV, hue='Species')
    plt.show()

plot_lm()

# 绘制热图，查看特征间相关性
def plot_heatmap():
    fig = plt.gcf()
    fig.set_size_inches(12, 8)
    fig = sns.heatmap(iris.corr(), annot=True, cmap='GnBu', linewidths=1, linecolor='k',
        square=True, mask=False, vmin=-1, vmax=1, cbar_kws={"orientation": "vertical"}, cbar=True)
    plt.show()

plot_heatmap()

# 数据预处理
X = iris[['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm']]
y = iris['Species']
encoder = LabelEncoder()
y = encoder.fit_transform(y)

# 数据分割
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.3, random_state=101)

# 定义评估模型的函数
def evaluate_model(model, train_X, train_y, test_X, test_y, model_name):
    model.fit(train_X, train_y)
    prediction = model.predict(test_X)
    accuracy = metrics.accuracy_score(prediction, test_y)
    print(f'{model_name} 的准确率是: {accuracy:.4f}')

# 使用不同模型进行评估
models = [
    (svm.SVC(), "支持向量机(SVM)"),
    (LogisticRegression(), "逻辑回归(Logistic Regression)"),
    (DecisionTreeClassifier(), "决策树(Decision Tree)"),
    (KNeighborsClassifier(n_neighbors=3), "K最近邻(KNN)")
]

for model, name in models:
    evaluate_model(model, train_X, train_y, test_X, test_y, name)

# 使用花瓣尺寸进行模型评估
petal = iris[['PetalLengthCm', 'PetalWidthCm', 'Species']]
train_p, test_p = train_test_split(petal, test_size=0.3, random_state=0)
train_x_p = train_p[['PetalWidthCm', 'PetalLengthCm']]
train_y_p = train_p.Species
test_x_p = test_p[['PetalWidthCm', 'PetalLengthCm']]
test_y_p = test_p.Species

# 使用花萼尺寸进行模型评估
sepal = iris[['SepalLengthCm', 'SepalWidthCm', 'Species']]
train_s, test_s = train_test_split(sepal, test_size=0.3, random_state=0)
train_x_s = train_s[['SepalWidthCm', 'SepalLengthCm']]
train_y_s = train_s.Species
test_x_s = test_s[['SepalWidthCm', 'SepalLengthCm']]
test_y_s = test_s.Species

# 评估不同特征的模型
for model, name in models:
    evaluate_model(model, train_x_p, train_y_p, test_x_p, test_y_p, f'{name} 使用花瓣')
    evaluate_model(model, train_x_s, train_y_s, test_x_s, test_y_s, f'{name} 使用花萼')
